<?php


namespace App\Models\CacheModel;


use App\Models\Api\BaseCache;
use think\Log;
use AstroTool\Cache\CacheManage;

class ZlAstrExerciseRecord extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.zl_astr_exercise_record';

    protected $cacheModel = 'astr_exercise.user_result';
    protected $cacheModel1 = 'astr_exercise.ranking';

    protected $cacheIdKey = 'id';

    /**
     * 设置缓存
     * @param $data
     * @param $uid
     * @throws \Exception
     */
    public function setCacheData($data, $uid)
    {
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setCache($data, 'details', false);
    }

    /**
     * 开启了缓存
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array|false|string
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            $answerResult = $this->whereIn('uid', $ids)
                ->column('id,uid,level,content1,content2,content3,content4,grade1,grade2,grade3,grade4,grade,level,create_time,update_time,status,answer_time,name,avatar', 'uid');
        }
        catch (\Exception $e)
        {
            Log::write('ZlAstrExerciseRecord用户答题状态信息异常：' . $e->getMessage(), 'error', true);
            return [];
        }

        return $answerResult;
    }

    /**
     * 获取排行榜数据
     * @param array $userinfo 自己的用户信息
     * @param string $oss OSS地址
     * @param int $grade 自己的分数
     * @param int $status 自己的挑战状态 1=>未完成第一关｜未参加 2=>参加了
     * @return array
     * @throws \Exception
     */
    public function getRanking($userinfo = [], string $oss, int $grade, int $status): array
    {
        $pageData = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel1)
            ->setPage(1)
            ->setPageSize(100)
            ->setSort('desc')
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc')
            {
                $resData = $this->getRankingIdsInData();
                if ($isCache)
                {
                    $data = [];
                    foreach ($resData as $uid => $score)
                    {
                        $data[$uid] = ['grade' => $score];
                    }
                    return $data;
                }
                return $resData;
            }, 'grade', 0);

        $uids = array_keys($pageData['data']);

        $userInfoList = $this->batchGetInfoByIds($uids, ['name', 'avatar']);

        $data = [];
        $i = 1;

        $userRanking = '100+';

        foreach ($pageData['data'] as $uid => $gradeItem)
        {
            if ($userinfo && $uid == $userinfo['id'])
            {
                $userRanking = $i;
                $name = $userinfo['nickname'] ?: '匿名用户';
                $avatar = $userinfo['avatar'] ? $oss . $userinfo['avatar'] : '/static/new_year_activ/img/avatar.png';
            } else
            {
                $name = isset($userInfoList[$uid]['name']) && $userInfoList[$uid]['name'] ? $userInfoList[$uid]['name'] : '匿名用户';
                $avatar = isset($userInfoList[$uid]['avatar']) && $userInfoList[$uid]['avatar'] ? $oss . $userInfoList[$uid]['avatar'] : '/static/new_year_activ/img/avatar.png';
            }

            $data[] = [
                'ranging' => $i,
                'name' => $name,
                'avatar' => $avatar,
                'grade' => (int)$gradeItem
            ];

            $i++;
        }

        if ($status === 1)
        {
            $userRanking = '暂无排名';
            $grade = '未完成';
        }
        if ($userinfo)
        {
            $selfRankingData = [
                'ranging' => $userRanking,
                'name' => $userinfo['nickname'] ?: '匿名用户',
                'avatar' => $userinfo['avatar'] ? $oss . $userinfo['avatar'] : '/static/new_year_activ/img/avatar.png',
                'grade' => $grade
            ];
        } else
        {
            $selfRankingData = null;
        }

        return [
            'rankList' => $data,
            'selfRanking' => $selfRankingData
        ];
    }

    /**
     * 更新 排行榜分数
     * @param $uid
     * @param $grade int   总分数
     * @param $answerTime int 总答题时长
     * @throws \Exception
     */
    public function changeRankingScore($uid, int $grade, int $answerTime): void
    {
        $score = $answerTime > 0 ? $grade + ((1000000 - $answerTime) / 1000000) : $grade;
        // 更新或添加用户排行榜信息
        CacheManage::getInstance()->setCacheConfig($this->cacheModel1, $uid)->listAdd([$uid => $score]);
    }

    /**
     * 获取排行榜前100名用户和分数
     * @return array
     */
    public function getRankingIdsInData()
    {
        try
        {
            $data = $this->order('grade desc,answer_time asc')->limit(100)->column('answer_time,grade', 'uid');

            $resData = [];
            foreach ($data as $uid => $datum)
            {
                if ($datum['answer_time'] > 0)
                {
                    $resData[$uid] = $datum['grade'] + ((1000000 - $datum['answer_time']) / 1000000);
                } else
                {
                    $resData[$uid] = $datum['grade'];
                }
            }
        }
        catch (\Exception $e)
        {
            return [];
        }

        return $resData;
    }
}
